package com.example.wxsmart.controller;

import com.example.wxsmart.config.WeiXinConfig;
import com.example.wxsmart.pojo.Question;
import com.example.wxsmart.resources.ElasticSearchDocumentResources;
import com.example.wxsmart.resources.KeyResources;
import com.example.wxsmart.resources.WeiXinMessageResources;
import com.example.wxsmart.util.weixinUtil.AesException;
import com.example.wxsmart.util.weixinUtil.WXBizMsgCrypt;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;

/**
 * @author Luojunxian
 * @data 2022/5/30 13:37
 * @classname WeiXinController
 */
@Api(tags = "微信api接口")
@Slf4j
@RestController
@RequestMapping("wx")
public class WeiXinController {

    @Resource
    private WeiXinConfig weiXinConfig;

    @Resource
    private WeiXinMessageResources weiXinMessageResources;

    @Resource
    private ElasticSearchDocumentResources documentResources;

    @Resource
    private KeyResources keyResources;

    WXBizMsgCrypt wxBizMsgCrypt;

    /**
     * 微信回调
     *
     * @param httpUtils http跑龙套
     * @return {@code String}
     * @throws AesException aes例外
     */
    @ApiOperation("微信回调接口")
    @GetMapping("/callBack")
    public String wxGet(HttpServletRequest httpUtils) throws AesException {
        log.info("开始验证微信回调");
        wxBizMsgCrypt = new WXBizMsgCrypt(weiXinConfig.getSToken(), weiXinConfig.getSEncodingAESKey(), weiXinConfig.getSCorpID());
        // 解析出url上的参数值如下：
        String sVerifyMsgSig = httpUtils.getParameter("msg_signature");
        String sVerifyTimeStamp = httpUtils.getParameter("timestamp");
        String sVerifyNonce = httpUtils.getParameter("nonce");
        String sVerifyEchoStr = httpUtils.getParameter("echostr");
        //需要返回的明文
        String sEchoStr = null;
        try {
            sEchoStr = wxBizMsgCrypt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
                    sVerifyNonce, sVerifyEchoStr);
            log.info("明文:{}", sEchoStr);
            log.info("微信回调成功");
            // 验证URL成功，将sEchoStr返回
        } catch (Exception e) {
            //验证URL失败，错误原因请查看异常
            e.printStackTrace();
        }

        return sEchoStr;
    }

    /**
     * 微信推送消息(含应用和客服消息)
     *
     * @param httpUtils http跑龙套
     * @throws AesException aes例外
     * @throws IOException
     */
    @ApiOperation(value = "微信推送消息(含应用和客服消息)")
    @PostMapping("/callBack")
    public void wxPost(HttpServletRequest httpUtils) throws AesException, IOException {
        log.info("开始接收微信信息");
        wxBizMsgCrypt = new WXBizMsgCrypt(weiXinConfig.getSToken(), weiXinConfig.getSEncodingAESKey(), weiXinConfig.getSCorpID());
        String sReqMsgSig = httpUtils.getParameter("msg_signature");
        String sReqTimeStamp = httpUtils.getParameter("timestamp");
        String sReqNonce = httpUtils.getParameter("nonce");
        // post请求的密文数据
        String sReqData;

        // 读取微信发送的xml消息
        BufferedReader streamReader = new BufferedReader(new InputStreamReader(httpUtils.getInputStream(), "UTF-8"));
        StringBuilder sb = new StringBuilder();
        String inputStr;
        while ((inputStr = streamReader.readLine()) != null) {
            sb.append(inputStr);
        }
        sReqData = sb.toString();
        try {
            String sMsg = wxBizMsgCrypt.DecryptMsg(sReqMsgSig, sReqTimeStamp, sReqNonce, sReqData);
            // TODO: 解析出明文xml标签的内容进行处理
            // For example:
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            StringReader sr = new StringReader(sMsg);
            InputSource is = new InputSource(sr);
            Document document = db.parse(is);

            Element root = document.getDocumentElement();
            NodeList nodelist = root.getElementsByTagName("Content");
            // 解析出来的消息
            String message = nodelist.item(0).getTextContent();
            log.info("解析出的消息:{}", message);

            log.info("进行消息回复并发送请求");

            String answer = "";

            String key = keyResources.getOperational(message);
            if(null != key) {
                // 是否是key操作
                log.info("开始进行key-value操作,操作为{}", key);
                answer = keyResources.operational(key, message);
            }else {
                // 向es搜索返回结果
                log.info("开始进行检索操作...");
                Question question = documentResources.searchDocument(message);
                answer = question == null ? weiXinMessageResources.getBaiDu(message) : question.toStrings();
            }

            // 发起回复Post请求
            weiXinMessageResources.sendMessage(answer);
        } catch (Exception e) {
            // 解密失败，失败原因请查看异常
            e.printStackTrace();
        }
    }


}
